package com.leetcode.根据算法进行分类.位运算相关;

/**
 * @author: ZhouBert
 * @date: 2021/3/29
 * @description:	190. 颠倒二进制位
 * https://leetcode-cn.com/problems/reverse-bits/
 */
public class A_190_颠倒二进制位 {
	public static void main(String[] args) {

	}

	/**
	 * 关于 Integer.reverse(n) 的详细解释：
	 * https://www.jianshu.com/p/be272c8704d9
	 * 第一步：
	 * 计算 i = (i & 0x55555555) << 1 | (i >>> 1) & 0x55555555( & 优先级大于 | ）
	 * 先计算：(i & 0x55555555) << 1 ，再计算 (i >>> 1) & 0x55555555( & 优先级大于 | ）
	 * 最后计算 | 进行合并，最后的结果就是 两两之间进行交换；
	 * 第二步：
	 * 同理完成 四四之间进行交换
	 * 第三步：
	 * 同理完成 八八之间进行交换
	 * 第四步：
	 * i << 24
	 * (i & 0xff00) << 8)
	 * (i >>> 8) & 0xff00
	 * (i >>> 24)
	 * 最后再或起来。
	 * --
	 * 也可以先进行 16 位交换，再8位...
	 * @param n
	 * @return
	 */
	public int reverseBits(int n) {
		return Integer.reverse(n);
	}

	/**
	 * https://leetcode-cn.com/problems/reverse-bits/solution/zhi-qi-ran-zhi-qi-suo-yi-ran-wei-yun-suan-jie-fa-x/
	 * 这样写似乎更清晰一些
	 * @param n
	 * @return
	 */
	public int reverseBitsByChange(int n) {
		n = (n >>> 16) | (n << 16);
		//1111 1111 0000 0000 1111 1111 0000 0000
		n = ((n & 0xff00ff00) >>> 8) | ((n & 0x00ff00ff) << 8);
		//1111 0000 1111 0000 1111 0000 1111 0000
		n = ((n & 0xf0f0f0f0) >>> 4) | ((n & 0x0f0f0f0f) << 4);
		//1100 1100 1100 1100 1100 1100 1100 1100
		n = ((n & 0xcccccccc) >>> 2) | ((n & 0x33333333) << 2);
		//1010 1010 1010 1010 1010 1010 1010 1010
		n = ((n & 0xaaaaaaaa) >>> 1) | ((n & 0x55555555) << 1);
		return n;
	}
}

